 aR  w Q m^9      h	 oP       nSystem-wide;--TstCtrls------------------------------------------------------
;
;----------------------------------------------------------------


;--InitRoutine---------------------------------------------------
;
;  Initialize variables
;
;----------------------------------------------------------------

PROCEDURE InitRoutine

  ; global variables
  error = 0

  ; event types
  nullEvent         = 0;
  penDownEvent      = 1;
  penUpEvent        = 2;
  keyDownEvent      = 3;
  keyUpEvent        = 4;
  characterEvent    = 5;
  enterWindowEvent  = 6;
  exitWindowEvent   = 7;
  controlEvent      = 8;
  menuEvent         = 9;
  dialogEvent       = 10;

  ; control types
  simpleCtrl    = 1;
  buttonCtrl    = 2;
  checkboxCtrl  = 3;
  radioCtrl     = 4;
  invButtonCtrl = 5;
  a3dButtonCtrl = 6;
  exitBoxCtrl   = 9;


  ; keys
  tabKey$       = CHR$(9)
  linefeedKey$  = CHR$(10)
  returnKey$    = CHR$(13)
  crLf$         = returnKey$ + linefeedKey$

  escapeKey$    = CHR$(27)
  confirmKey$   = CHR$(141)
  helpKey$      = CHR$(191)
  duplicateKey$ = CHR$(228)
  eraseKey$     = CHR$(229)
  findKey$      = CHR$(230)
  insertKey$    = CHR$(233)
  moveKey$      = CHR$(237)
  wildcardKey$  = CHR$(247)

ENDP
;$EJECT

;--DrawLine------------------------------------------------------
;
;  This draws vertical or horizontal lines using erase and invert
;
;----------------------------------------------------------------

PROCEDURE DrawLine topLeftX, topLeftY, extentX, extentY

  EraseBox topLeftX, topLeftY, extentX, extentY
  InvertBox topLeftX, topLeftY, extentX, extentY

ENDP
;$EJECT

;--TicTacToe-----------------------------------------------------
;
;  Tic Tac Toe game for the demo
;
;  Since GRiDTask doesn't have arrays, I'm going to use strings
;  to store the results of the game.
;
;  If you assign a value to each square on the tic-tac-toe board
;  from 0 to 8, then you can represent the possible ways that someone
;  can win with the number sequences 012, 345, 678, 036, 147, 258, 048 & 246.
;  If these numbers are converted to words with the appropriate bits set then
;  you would have the following:
;
;    012 = 007 (007H), 345 = 056 (038H), 678 = 448 (1C0H), 036 = 073 (049H)
;    147 = 146 (192H), 258 = 292 (124H), 048 = 273 (111H), 246 = 084 (054H)
;
;  These are the values to "AND" with to test for a won game.
;
;  The variable turn keeps track of who's turn it is.
;  When turn is 1, it is "x"'s turn; when it is -1, it is "o"'s turn
;  The variable xTurn keeps track of which part of x's turn is being
;  done (this being the first stroke or the second stroke)
;
;----------------------------------------------------------------

PROCEDURE TicTacToe

LOCALS boardExtX, boardExtY, boardTLX, boardTLY, board13, board23, _
       event, penDown, x, y, data1, data2, data3, error, reOriented, _
       restarting, choosingFirst, lineThickness, done, match, msgTLX, _
       lastX, lastY, box, turn, xTurn, midX, xFirstButtonID, oFirstButtonID, _
       box1, box1TLX, box1TLY, box2, box2TLX, box2TLY, box3, box3TLX, box3TLY, _
       winner$, xyChar$, position, placesX, placesO, placesFree, placesDone

  lineThickness = 3
  reOriented = TRUE

  done = FALSE
  WHILE NOT done
    IF reOriented THEN
      ; make the size of the tic-tac-toe board be centered within the smaller
      ; dimension of height and width & make sure that it is a multiple of 3

      IF WinMaxY < WinMaxX THEN
        boardExtX = WinMaxY
      ELSE
        boardExtX = WinMaxX
      ENDIF
      boardExtX = TRUNC((boardExtX * .75) / 3) * 3
      boardExtY = boardExtX

      ; center the board (the imaginary topLeft) on the display
 
      boardTLX = (WinMaxX - boardExtX) / 2
      boardTLY = (WinMaxY - boardExtX) / 2
      board13 = boardExtX / 3
      board23 = board13 + board13

      ; put up a simple menu bar with only an exit choice

      MenuBar "  File|  Direction|"
      Menu 1, "Quit~"
      Menu 2, "North~West~South~East~"

      reOriented = FALSE
      reStarting = TRUE
    ENDIF

    IF restarting THEN
      choosingFirst = TRUE
      EraseBox 0, CharHeight * 2, -1, -1
      msgTLX = boardTLX + (boardExtX - (CharWidth * 33)) / 2
      Cursor msgTLX, boardTLY + board13
      Print "Player who starts is     or     ?"
      xFirstButtonID = DrawButton _
        (buttonCtrl, msgTLX + CharWidth * 21, boardTLY + board13, -1, -1, " X ")
      oFirstButtonID = DrawButton _
        (buttonCtrl, msgTLX + CharWidth * 28, boardTLY + board13, -1, -1, " O ")
      FrameBox msgTLX - CharWidth, boardTLY + board13 - CharHeight, _
               CharWidth * 35, CharHeight * 3
      FrameBox msgTLX - CharWidth - 2, boardTLY + board13 - CharHeight - 2, _
               (CharWidth * 35) + 4, (CharHeight * 3) + 4
      restarting = FALSE
    ENDIF

    event = GetNextEvent (@penDown, @x, @y, @data1, @data2, @data3, @error)
    IF event = menuEvent THEN
      IF (data1 = 1) AND (data2 = 1) THEN
        done = TRUE
      ELSE IF (data1 = 2) THEN
        SetDisplayOrientation (data2 - 1)
        reOriented = TRUE
      ENDIF: ENDIF
    ELSE IF choosingFirst THEN
      IF event = controlEvent THEN
        IF (data1 = xFirstButtonID) OR (data1 = oFirstButtonID) THEN
          IF data1 = xFirstButtonID THEN turn = 1 ELSE turn = -1 ENDIF
          DeleteButton xFirstButtonID
          DeleteButton oFirstButtonID
          midX = FALSE
          xTurn = 0
          placesX = 0
          placesO = 0
          placesFree = 0
          placesDone = 0
          EraseBox 0, CharHeight * 2, -1, -1
          DrawLine boardTLX + board13 - 1, boardTLY, lineThickness, boardExtY
          DrawLine boardTLX + board23 - 1, boardTLY, lineThickness, boardExtY
          DrawLine boardTLX, boardTLY + board13 - 1, boardExtX, lineThickness
          DrawLine boardTLX, boardTLY + board23 - 1, boardExtX, lineThickness
          choosingFirst = FALSE
        ENDIF
      ENDIF
    ELSE IF event = penDownEvent THEN
      GetPoint @x, @y, @penDown
      box = (TRUNC((x-boardTLX)/board13)) + (TRUNC((y-boardTLY)/board13) * 3)
      position = 2^box
      WHILE penDown
        lastX = x
        lastY = y
        GetPoint @x, @y, @penDown

        ; This is here to make InvertLine look like a draw line

        IF x < lastX THEN lastX = lastX - 1
        ELSE IF x > lastX THEN lastX = lastX + 1 ENDIF: ENDIF
        IF y < lastY THEN lastY = lastY - 1
        ELSE IF y > lastY THEN lastY = lastY + 1 ENDIF: ENDIF

        IF penDown THEN
          InvertLine lastX, lastY, x, y
        ENDIF
      WEND

      ; Determine whether an 'O' or an 'X' or part of the 'X' was drawn

      IF (placesFree AND position) = 0 THEN
        IF turn = 1 THEN
          IF xTurn = 0 THEN
            xTurn = 1
            midX = TRUE
          ELSE
            placesX = placesX + position
            placesFree = placesFree + position
            placesDone = placesDone + 1
            midX = FALSE
            turn = -1
          ENDIF
        ELSE
          placesO = placesO + position
          placesFree = placesFree + position
          placesDone = placesDone + 1
          turn = 1
          xTurn = 0
        ENDIF
      ENDIF

      ; Don't look for winners unless the number of places filled > 4

      IF (placesDone > 4) AND (NOT midX) THEN
        match = 0
        IF      ((placesX AND 007) = 007) THEN match = 123
        ELSE IF ((placesX AND 056) = 056) THEN match = 456
        ELSE IF ((placesX AND 448) = 448) THEN match = 789
        ELSE IF ((placesX AND 073) = 073) THEN match = 147
        ELSE IF ((placesX AND 146) = 146) THEN match = 258
        ELSE IF ((placesX AND 292) = 292) THEN match = 369
        ELSE IF ((placesX AND 273) = 273) THEN match = 159
        ELSE IF ((placesX AND 084) = 084) THEN match = 357
        ELSE IF ((placesO AND 007) = 007) THEN match = 1123
        ELSE IF ((placesO AND 056) = 056) THEN match = 1456
        ELSE IF ((placesO AND 448) = 448) THEN match = 1789
        ELSE IF ((placesO AND 073) = 073) THEN match = 1147
        ELSE IF ((placesO AND 146) = 146) THEN match = 1258
        ELSE IF ((placesO AND 292) = 292) THEN match = 1369
        ELSE IF ((placesO AND 273) = 273) THEN match = 1159
        ELSE IF ((placesO AND 084) = 084) THEN match = 1357
        ENDIF: ENDIF: ENDIF: ENDIF: ENDIF: ENDIF: ENDIF: ENDIF
        ENDIF: ENDIF: ENDIF: ENDIF: ENDIF: ENDIF: ENDIF: ENDIF

        IF match <> 0 THEN
          xyChar$ = "X"
          IF match > 1000 THEN
            match = match - 1000
            xyChar$ = "O"
          ENDIF

          box1 = VAL(MID$(STR$(match),1,1))
          box2 = VAL(MID$(STR$(match),2,1))
          box3 = VAL(MID$(STR$(match),3,1))

          box1TLX = boardTLX + TRUNC((box1-1) MOD 3)*board13 + 3
          box1TLY = boardTLY + TRUNC((box1-1)/3)*board13 + 3
          box2TLX = boardTLX + TRUNC((box2-1) MOD 3)*board13 + 3
          box2TLY = boardTLY + TRUNC((box2-1)/3)*board13 + 3
          box3TLX = boardTLX + TRUNC((box3-1) MOD 3)*board13 + 3
          box3TLY = boardTLY + TRUNC((box3-1)/3)*board13 + 3

          InvertBox box1TLX, box1TLY, board13 - 5, board13 - 5
          InvertBox box2TLX, box2TLY, board13 - 5, board13 - 5
          InvertBox box3TLX, box3TLY, board13 - 5, board13 - 5
        ENDIF

        IF match <> 0 THEN
          winner$ = xyChar$ + " is the winner !!!"
        ELSE IF placesDone = 9 THEN
          winner$ = "Tim (cat) is the winner !!!"
        ENDIF: ENDIF

        IF (match <> 0) OR (placesDone = 9) THEN
          CURSOR 0, boardTLY + boardExtY + CharHeight
          CENTER winner$
          Delay (3)
        ENDIF

        IF match <> 0 THEN
          InvertBox box1TLX, box1TLY, board13 - 5, board13 - 5
          InvertBox box2TLX, box2TLY, board13 - 5, board13 - 5
          InvertBox box3TLX, box3TLY, board13 - 5, board13 - 5
        ENDIF

        IF (match <> 0) OR (placesDone = 9) THEN
          ERASEBOX boardTLX, boardTLY + boardExtY + CharHeight, _
                   boardExtX, CharHeight
          restarting = TRUE
        ENDIF
      ENDIF
    ENDIF: ENDIF: ENDIF
  WEND

  ClearScreen
ENDP
;$EJECT

;--Main----------------------------------------------------------
;
;  This starting point is here for testing controls and scribbling
;
;----------------------------------------------------------------

BREAKONKEY "|z"
InitRoutine

INSTALL "``Programs`TskCtrls~Lib~"
InitializeGRiDPad @error

IF error = 0 THEN
  TicTacToe
ELSE
  STACKMSG "GRiDPad Initialization failed with error: " + STR$(error)
  PAUSE ""
ENDIF

TerminateGRiDPad
REMOVELIB "TskCtrls"

STOP
